<?php

namespace app\common\service;

use app\common\exception\MiException;
use app\common\job\Queue;
use app\common\service\traits\InstanceTrait;
use app\model\site\User;
use app\model\site\UserPointsLog;
use app\model\store\DistRewardLog;
use app\model\store\Goods;
use app\model\store\Order;
use app\model\store\OrderItem;
use app\model\store\StoreManager;
use app\model\store\StoreManagerBalanceLog;
use app\model\store\UserCoupon;
use app\uniapp\service\OrderService;
use app\uniapp\service\UniAuthService;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Db;

class CommonOrderService
{

    use InstanceTrait;

    /** 创建订单
     * @throws DataNotFoundException
     * @throws MiException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function create($order){

        if(!isset($order['site_id'])) throw new MiException('缺少订单参数：site_id');
        if(!isset($order['platform'])) throw new MiException('缺少订单参数：platform');
        if(!isset($order['order_type'])) throw new MiException('缺少订单参数：order_type');
        if(!isset($order['delivery_type'])) throw new MiException('缺少订单参数：delivery_type');
        if(!isset($order['items'])) throw new MiException('缺少订单参数：items');
        if(!isset($order['num'])) throw new MiException('缺少订单参数：num');
        if(!isset($order['is_single'])) throw new MiException('缺少订单参数：is_single');
        if(!isset($order['total_price'])) throw new MiException('缺少订单参数：total_price');
        if(!isset($order['pay_price'])) throw new MiException('缺少订单参数：pay_price');
        if(!isset($order['order_status'])) throw new MiException('缺少订单参数：order_status');

        $platform = $order['platform'];
        if ($platform == 'cashier'){
            if(!isset($order['site_user_id'])) throw new MiException('缺少订单参数：site_user_id');    // 收银员
        }else{
            if(!isset($order['user_id'])) throw new MiException('缺少订单参数：user_id');
        }
        $deliveryType = $order['delivery_type'];
        $items = $order['items'];
        unset($order['items']);
        $order['order_no'] = makeOrderNo();

        if ($order['user_id']??0){

            $user = User::lock(true)->find($order['user_id']);

            // 使用了积分
            if ($order['points_num']){
                $payPrice = $order['total_price'] - $order['coupon_price'];
                // 验证积分是否足够
                $pointsConfig = CommonSiteConfigService::instance()->getConfigValue($order['site_id'], CommonSiteConfigService::POINTS);
                $needPoints = floor($payPrice * $pointsConfig['money_rate']);
                if ($needPoints != $order['points_num'] || $needPoints > $user->points){
                    throw new MiException("积分不足");
                }
                // 扣除积分
                User::where('id', UniAuthService::instance()->getLoginId())->dec('points', $order['points_num'])->update();
            }

            // 使用了优惠券
            if ($order['user_coupon_id']??0){
                // 修改优惠券使用状态为已使用
                UserCoupon::update(['is_has_use' => 1],['id'=>$order['user_coupon_id']]);
            }

        }

        Db::startTrans();
        try {
            // 创建订单
            $createOrder = Order::create($order);
            // 创建订单商品
            foreach ($items as $item) {

                if(!isset($item['site_id'])) throw new MiException("缺少订单商品参数：site_id");
                if(!isset($item['goods_id'])) throw new MiException("缺少订单商品参数：goods_id");
                if(!isset($item['goods_image'])) throw new MiException("缺少订单商品参数：goods_image");
                if(!isset($item['goods_title'])) throw new MiException("缺少订单商品参数：goods_title");
                if(!isset($item['price'])) throw new MiException("缺少订单商品参数：price");
                if(!isset($item['num'])) throw new MiException("缺少订单商品参数：num");
                if(!isset($item['pay_price'])) throw new MiException("缺少订单商品参数：pay_price");
                if(!isset($item['total_price'])) throw new MiException("缺少订单商品参数：total_price");

                if ($order['user_id']??0){
                    if (!isset($item['user_id'])) throw new MiException("缺少订单商品参数：user_id");
                }

                $goods = Goods::lock(true)->find($item['goods_id']);
                $item['order_id'] = $createOrder->id;
                if ($goods->spec_type == 2){    // 多规格
                    if(!$item['goods_sku_id']??0) throw new MiException("缺少订单商品参数：goods_sku_id");
                    if(!$item['goods_sku']??'') throw new MiException("缺少订单商品参数：goods_sku");
                }
                OrderItem::create($item);
                // 商品库存处理（先判断是否下单减库存）
                if ($goods->dec_stock_type == 1){   // 下单减库存（增加销量）
                    CommonGoodsService::instance()->decStock($goods, $item['num'], $item['goods_sku_id']??0);
                }
            }
            // 提交事务
            Db::commit();
            return $order;
        }catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw new MiException($e->getMessage());
        }
    }


    /**
     * 取消订单（未付款订单）
     * @param int $orderId
     * @param string $closeType
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws MiException
     * @throws ModelNotFoundException
     */
    public function cancel(int $orderId, string $closeType){
        $order = Order::find($orderId);
        if ($order->order_status == 'unpaid'){

            Db::startTrans();
            try {
                // 返还积分
                User::where('id', $order->userId)->inc('points', $order->points_num)->update();

                // 返还优惠券
                if ($order->coupon_id){
                    UserCoupon::update(['is_has_use' => 0],['id'=>$order->coupon_id]);
                }
                // 如果是下单减库存，回滚库存
                foreach ($order->items as $vo){
                    $goods = Goods::lock(true)->find($vo->goods_id);
                    if ($goods->dec_stock_type == 1){   // 下单减库存的商品
                        CommonGoodsService::instance()->rollbackStock($goods, $vo->num, $vo->goods_sku_id);
                    }
                }
                // 返还样品基金
                if ($order->store_manager_price){   // 扣除样品基金
                    StoreManager::where('user_id', $order->user_id)->inc('balance', $order->store_manager_price)->update();
                }

                $order->close_type = $closeType;
                $order->close_time = time();
                $order->order_status = 'close';
                $order->save();

                Db::commit();
            } catch (\Exception $e){
                Db::rollback();
                throw new MiException(print_r($e->getTraceAsString()));
            }
        }

    }

    /**
     * 关闭订单
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     * @throws MiException
     */
    public function close(int $orderId, string $closeType){

        // $closeType
        // auto - 到期关闭（已收货的订单到期自动关闭）
        // cancel - 取消关闭 （未付款的订单关闭）
        // admin - 商家后台关闭 （商品缺货，或其他原因，管理员手动取消订单）

        Db::startTrans();
        try {
            $order = Order::with(['items'])->lock(true)->find($orderId);
            if (!$order) throw new MiException("缺少订单信息");

            $order->close_type = $closeType;
            $order->close_time = time();
            $order->order_status = 'close';
            $order->save();

            Db::commit();
        } catch (\Exception $e){
            Db::rollback();
            throw new MiException(print_r($e->getTraceAsString()));
        }

    }


    /**
     * 确认收货
     * @param $orderId
     * @return void
     */
    public function receive($orderId){
        Db::transaction(function () use($orderId) {
            $order = Order::lock(true)->find($orderId);
            $user = User::lock(true)->find($order->user_id);
            if ($order && $order->order_status == 'receive'){
                $order->order_status = 'reply'; // 待评论
                $order->save();
                // 赠送积分
                $pointsConfig = CommonSiteConfigService::instance()->getConfigValue($order->site_id, CommonSiteConfigService::POINTS);
                if ($pointsConfig['give_points_rate']>0){   // 商家开启了消费赠送积分
                    $points = floor($order->pay_price * $pointsConfig['give_points_rate']);
                    if ($points >= 1) { // 满1积分才赠送
                        $user->points += $points;
                        // 创建积分明细
                        UserPointsLog::create([
                            'site_id' => $order->site_id,
                            'user_id' => $order->user_id,
                            'price' => $order->pay_price,
                            'num' => $points,
                            'rel_model' => 'order',
                            'rel_id' => $order->id,
                            'note' => "消费赠送"
                        ]);
                    }

                }

                // 增加消费总金额
                $user->total_price += $order->pay_price;
                // 增加成长值
                $user->growth += floor($order->pay_price);
                // 保存
                $user->save();
                // 更新会员等级
                CommonUserService::instance()->updateLevel($user);

                // 发送到期关闭订单的队列消息
                $config = CommonSiteConfigService::instance()->getConfigValue($order->site_id, CommonSiteConfigService::STORE);
                $delay = $config['order_close_delay'];
                Queue::instance()->send('orderClose', ['order_id' => $order->id], $delay);
            }
        });
    }


    /**
     * 订单支付成功后的功能逻辑
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     * @throws MiException
     */
    public function paySuccess(string $payType, Order $order, array $params=[]){
        if ($order->order_status == 'unpaid') {

            // 付款时间
            $order->pay_time = time();

            if ($order->order_type == 'group' && $order->is_single!=1){ // 拼团订单，且不是单独购买
                $order->order_status = 'paid';  // 已付款
            }else{
                $order->order_status = 'wait';  // 待发货
            }

            if ($payType == 'points'){
                $order->pay_type = 'points';
            }else if ($payType == 'wx'){
                $order->pay_order_no = $params['transaction_id'];
                $order->pay_time = $params['success_time'];
            }elseif ($payType == 'balance') {
                $order->pay_type = 'balance';
                // 扣除余额
                User::where('id', $order->user_id)->dec('balance', $order->pay_price)->update();
            }

            $order->save();
            $siteId = $order->site_id;
            $uid = $order->user_id;

            // 减库存
            foreach ($order->items as $vo){
                $goods = Goods::lock(true)->find($vo->goods_id);
                if ($goods->dec_stock_type == 2){   // 付款减库存的商品
                    CommonGoodsService::instance()->decStock($goods, $vo->num, $vo->goods_sku_id);
                }
            }

            if ($order->store_manager_price){    // 基金抵扣记录
                StoreManagerBalanceLog::create([
                    'site_id' => $siteId,
                    'user_id' => $uid,
                    'rel_id' => $order->id,
                    'rel_model' => 'order',
                    'reward_type' => 3,
                    'note' => '消费抵扣',
                    'amount' => $order->store_manager_price * -1,
                    'rate' => 0,
                    'price' => 0,
                ]);
            }

            if ($order->points_price > 0){  // 使用了积分抵扣
                // 创建积分抵扣记录
                // **注意**  积分已在创建订单时扣除
                UserPointsLog::create([
                    'site_id' => $siteId,
                    'user_id' => $uid,
                    'price' => $order->points_price,
                    'amount' => $order->points_num * -1,
                    'rel_model' => 'order',
                    'rel_id' => $order->id,
                    'change_type' => 3,
                    'note' => "积分抵扣"
                ]);
            }

            if ($order->user_coupon_id){    // 使用了优惠券
                UserCoupon::update(['is_has_use' => 1], ['id' => $order->user_coupon_id]);
            }

            // 发放佣金
            CommonDistService::instance()->giveRewardByOrder($order);

        }
    }
}
